package com.wenlin.myproduction.ui;

import android.content.ClipboardManager;
import android.content.Intent;
import android.os.Bundle;

import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.wenlin.myproduction.R;
import com.wenlin.myproduction.base.BaseActivity;
import com.wenlin.myproduction.base.BaseSwipeActivity;
import com.wenlin.myproduction.bean.Get24PointsBean;
import com.wenlin.myproduction.bean.SelectNumber;
import com.wenlin.myproduction.binder.Get24PointsBinder;
import com.wenlin.myproduction.binder.SelectNumberBinder;
import com.wenlin.myproduction.util.Checker;
import com.wenlin.myproduction.util.MyGridLayoutManager;
import com.wenlin.myproduction.util.ToastUtils;
import com.wenlin.myproduction.util.TypeData;
import com.wenlin.myproduction.util.TypeDataNames;
import com.wenlin.myproduction.util.ValCommon;

import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import me.drakeet.multitype.Items;
import me.drakeet.multitype.MultiTypeAdapter;

/**
 * @author 文琳
 * @Email 377979485@qq.com
 * @desc 算24点工具
 * @time 2022-12-20 星期二 20:13
 */
public class Get24PointsActivity extends BaseSwipeActivity {
    @BindView(R.id.rv)
    RecyclerView rv;

    private Items items;
    private MultiTypeAdapter adapter;
    private static final String PLUS = "+";
    private static final String MINUS = "-";
    private static final String MULTI = "*";
    private static final String DIVISION = "/";
    private static String[] ARR_CAL_METHODS = {PLUS, MINUS, MULTI, DIVISION};

    public static void start(BaseActivity activity) {
        Intent intent = new Intent(activity, Get24PointsActivity.class);
        activity.startActivity(intent);
    }

    @Override
    public int getContentView() {
        return R.layout.activity_get_24_points;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setTitle(ValCommon.GET_24_POINTS_GAME);
        items = new Items();
        adapter = new MultiTypeAdapter(items);
        adapter.register(SelectNumber.class, new SelectNumberBinder());
        adapter.register(Get24PointsBean.class, new Get24PointsBinder());
        MyGridLayoutManager layoutManager = new MyGridLayoutManager(this, 13);
        layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                return items.get(position) instanceof SelectNumber ? 1 : 13;
            }
        });
        rv.setLayoutManager(layoutManager);
        rv.setHasFixedSize(true);
        rv.setAdapter(adapter);
        initData();
    }

    /**
     * 初始化数据
     */
    private void initData() {
        if (Checker.hasList(items)) {
            items.clear();
            adapter.notifyDataSetChanged();
        }
        List<SelectNumber> list = new ArrayList<>();
        for (int i = 0; i < 13 * 4; i++) {
            list.add(new SelectNumber(i, i % 13 + 1, false));
        }
        items.addAll(list);
        adapter.notifyDataSetChanged();
    }

    /**
     * 破解答案
     *
     * @param list 四个数字的数组
     */
    private void figureOut(List<Integer> list) {
        //四个数字取两个数字，加减乘除之后的结果再和剩下的两个数组成池子，依次循环
        float firstNum1, secondNum1;//第一次参与运算的两个数称为第一个数和第二个数
        float firstNum2, secondNum2;//第二次
        float firstNum3, secondNum3;//第三次
        float[] arrThreeNumbers = new float[3];//用来存放第一次运算后，剩余的三个数字
        float[] arrTwoNumbers = new float[2];//用于存放第二次运算后，剩余的两个数字
        //一、从四个数字中取两个数字进行第一次运算
        for (int i = 0; i < list.size(); i++) {//确定第一个数
            firstNum1 = list.get(i);
            for (int j = 0; j < list.size(); j++) {//确定第二个数
                if (j == i) continue;
                secondNum1 = list.get(j);
                for (int position1 = 0; position1 < ARR_CAL_METHODS.length; position1++) {//确定运算符，ARR_CAL_METHODS包括加减乘除
                    if (secondNum1 == 0 && ARR_CAL_METHODS[position1].equals(DIVISION))
                        continue;//跳过除数是0的情况
                    float result1 = getResult(firstNum1, secondNum1, ARR_CAL_METHODS[position1]);//第一次运算的结果
                    int positionThreeNumbers = 0;
                    arrThreeNumbers[positionThreeNumbers++] = result1;
                    for (int k = 0; k < list.size(); k++) {
                        if (k == i) continue;
                        if (k == j) continue;
                        arrThreeNumbers[positionThreeNumbers++] = list.get(k);
                    }
                    //二、从三个数字中取两个数字进行第二次运算
                    for (int k = 0; k < arrThreeNumbers.length; k++) {//确定第二次运算的第一个数
                        firstNum2 = arrThreeNumbers[k];
                        for (int l = 0; l < arrThreeNumbers.length; l++) {//确定第二次运算的第二个数
                            if (l == k) continue;
                            secondNum2 = arrThreeNumbers[l];
                            for (int position2 = 0; position2 < ARR_CAL_METHODS.length; position2++) {//确定运算符，ARR_CAL_METHODS包括加减乘除
                                if (secondNum2 == 0 && ARR_CAL_METHODS[position2].equals(DIVISION))
                                    continue;//跳过除数是0的情况
                                float result2 = getResult(firstNum2, secondNum2, ARR_CAL_METHODS[position2]);//第二次运算的结果
                                int positionTwoNumbers = 0;
                                arrTwoNumbers[positionTwoNumbers++] = result2;
                                for (int m = 0; m < arrThreeNumbers.length; m++) {
                                    if (m == k) continue;
                                    if (m == l) continue;
                                    arrTwoNumbers[positionTwoNumbers++] = arrThreeNumbers[m];
                                }
                                //三、从两个数字中取两个数字进行第三次运算（这里为了好理解，才用了数组存放两个数字，若是直接拿出参加运算也可以）
                                for (int m = 0; m < arrTwoNumbers.length; m++) {//确定第三次运算的第一个数
                                    firstNum3 = arrTwoNumbers[m];
                                    for (int n = 0; n < arrTwoNumbers.length; n++) {//确定第三次运算的第二个数
                                        if (n == m) continue;
                                        secondNum3 = arrTwoNumbers[n];
                                        //执行加减乘除
                                        for (int position3 = 0; position3 < ARR_CAL_METHODS.length; position3++) {//确定运算符，ARR_CAL_METHODS包括加减乘除
                                            if (secondNum3 == 0 && ARR_CAL_METHODS[position3].equals(DIVISION))
                                                continue;
                                            float result3 = getResult(firstNum3, secondNum3, ARR_CAL_METHODS[position3]);//第三次运算的结果
                                            //将结果是24的情况解析、记录并显示出来
                                            if (result3 == 24f) {
                                                String first = String.valueOf(list.get(i));
                                                String firstMethod = ARR_CAL_METHODS[position1];
                                                String second = String.valueOf(list.get(j));
                                                String firstResult = String.valueOf(result1);
                                                String third = String.valueOf(arrThreeNumbers[k]);
                                                String secondMethod = ARR_CAL_METHODS[position2];
                                                String fourth = String.valueOf(arrThreeNumbers[l]);
                                                String secondResult = String.valueOf(result2);
                                                String fifth = String.valueOf(arrTwoNumbers[m]);
                                                String thirdMethod = ARR_CAL_METHODS[position3];
                                                String sixth = String.valueOf(arrTwoNumbers[n]);
                                                String thirdResult = String.valueOf(result3);
                                                //简单查重
                                                boolean hasAlready = false;
                                                if (items != null && items.size() > 0) {
                                                    for (int o = 0; o < items.size(); o++) {
                                                        Object object = items.get(o);
                                                        if (object instanceof Get24PointsBean) {
                                                            Get24PointsBean temp = (Get24PointsBean) object;
                                                            if (temp.getFirstMethod().equals(firstMethod) && temp.getResult1().equals(firstResult)
                                                                    || temp.getFirstMethod().equals(secondMethod) && temp.getResult1().equals(secondResult)) {//第三次运算的结果必定是24，所以只需要看前两次的运算符与运算结果是否同时重复
                                                                hasAlready = true;
                                                                break;
                                                            }
                                                        }
                                                    }
                                                }
                                                //如果是新解法，则加入RecyclerView显示出来
                                                if (!hasAlready) {
                                                    items.add(new Get24PointsBean(items.size() - 13 * 4 + 1, list, first, second, third, fourth, fifth, sixth, firstResult, secondResult, thirdResult, firstMethod, secondMethod, thirdMethod));
                                                    adapter.notifyDataSetChanged();
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        ToastUtils.getInstance().showSuccess("总共找出" + (items.size() - 13 * 4) + "种结果");
    }

    /**
     * 运算获取结果
     *
     * @param left      运算符左边的数
     * @param right     运算符右边的数
     * @param calMethod 运算符
     * @return 所求
     */
    private float getResult(float left, float right, String calMethod) {
        float result = 0;
        switch (calMethod) {
            case PLUS:
                result = left + right;
                break;
            case MINUS:
                result = left - right;
                break;
            case MULTI:
                result = left * right;
                break;
            case DIVISION:
                if (right != 0) result = left / right;
                else result = -1;
                break;
            default:
        }
        return result;
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void threadHandle(TypeData typeData) {
        String name = typeData.getName();
        if (name.equals(TypeDataNames.clickCopyButton)) {
            String bean = (String) typeData.getData();
            if (Checker.notNull(bean)) {
                ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
                if (Checker.notNull(clipboardManager)) {
                    clipboardManager.setText(bean);
                    ToastUtils.getInstance().showSuccess("已复制");
                }
            }
        }
        if (name.equals(TypeDataNames.clickSelectNumber)) {
            SelectNumber selectNumber = (SelectNumber) typeData.getData();
            if (Checker.isNull(selectNumber)) return;
            if (Checker.hasNoList(items)) return;
            boolean targetChecked = !(selectNumber.isChecked());
            //四排1-13,共52个数，每一排选中数字可为0或1个。
            //目标数字设置为相反状态，原本选中改为未选中，原本未选中改成选中
            for (Object o :
                    items) {
                if (o instanceof SelectNumber) {
                    SelectNumber temp = (SelectNumber) o;
                    if (temp.getId() == selectNumber.getId()) {
                        temp.setChecked(targetChecked);
                        break;
                    }
                }
            }
            adapter.notifyDataSetChanged();
            //检查更改了数字为选中状态的那一排，其他数字的选中状态为未选中
            for (Object o :
                    items) {
                if (o instanceof SelectNumber) {
                    SelectNumber temp = (SelectNumber) o;
                    if (targetChecked) {//当选中某个数时，那一行其他选中数字变未选中
                        if (selectNumber.getId() < 13 && temp.getId() < 13 && temp.getId() != selectNumber.getId())
                            temp.setChecked(false);
                        else if (selectNumber.getId() < 26 && selectNumber.getId() >= 13 && temp.getId() < 26 && temp.getId() >= 13 && temp.getId() != selectNumber.getId())
                            temp.setChecked(false);
                        else if (selectNumber.getId() < 39 && selectNumber.getId() >= 26 && temp.getId() < 39 && temp.getId() >= 26 && temp.getId() != selectNumber.getId())
                            temp.setChecked(false);
                        else if (selectNumber.getId() < 52 && selectNumber.getId() >= 39 && temp.getId() < 52 && temp.getId() >= 39 && temp.getId() != selectNumber.getId())
                            temp.setChecked(false);
                    }
                }
            }
            adapter.notifyDataSetChanged();
            //检查是否选中四个数字
            List<Integer> list = new ArrayList<>();
            for (Object o :
                    items) {
                if (o instanceof SelectNumber) {
                    SelectNumber temp = (SelectNumber) o;
                    if (temp.isChecked()) {
                        list.add(temp.getNum());
                    }
                }
            }
            adapter.notifyDataSetChanged();
            if (list.size() == 4) {
                List<Object> listOri = new ArrayList<>();
                for (Object o :
                        items) {
                    if (o instanceof SelectNumber) {
                        listOri.add(o);
                    } else break;
                }
                items.clear();
                adapter.notifyDataSetChanged();
                items.addAll(listOri);
                adapter.notifyDataSetChanged();
                figureOut(list);
            }
        }
    }
}
